home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / tutorials / custEducation / opengl2 / lib / shapes.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-11  |  28.9 KB  |  1,091 lines

  1. /*
  2.  * (c) Copyright 1993, Silicon Graphics, Inc.
  3.  * ALL RIGHTS RESERVED 
  4.  * Permission to use, copy, modify, and distribute this software for 
  5.  * any purpose and without fee is hereby granted, provided that the above
  6.  * copyright notice appear in all copies and that both the copyright notice
  7.  * and this permission notice appear in supporting documentation, and that 
  8.  * the name of Silicon Graphics, Inc. not be used in advertising
  9.  * or publicity pertaining to distribution of the software without specific,
  10.  * written prior permission. 
  11.  *
  12.  * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
  13.  * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
  14.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
  15.  * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
  16.  * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
  17.  * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
  18.  * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
  19.  * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
  20.  * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
  21.  * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
  22.  * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
  23.  * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
  24.  * 
  25.  * US Government Users Restricted Rights 
  26.  * Use, duplication, or disclosure by the Government is subject to
  27.  * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
  28.  * (c)(1)(ii) of the Rights in Technical Data and Computer Software
  29.  * clause at DFARS 252.227-7013 and/or in similar or successor
  30.  * clauses in the FAR or the DOD or NASA FAR Supplement.
  31.  * Unpublished-- rights reserved under the copyright laws of the
  32.  * United States.  Contractor/manufacturer is Silicon Graphics,
  33.  * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
  34.  *
  35.  * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
  36.  */
  37. #include <stdio.h>
  38. #include <math.h>
  39. #include <GL/gl.h>
  40. #include <GL/glu.h>
  41. #include "3d.h"
  42.  
  43. #define SPHEREWIRE    0
  44. #define CUBEWIRE    1
  45. #define BOXWIRE        2
  46. #define TORUSWIRE    3
  47. #define CYLINDERWIRE    4
  48. #define ICOSAWIRE    5
  49. #define OCTAWIRE    6
  50. #define TETRAWIRE    7
  51. #define DODECAWIRE    8
  52. #define CONEWIRE    9
  53. #define SPHERESOLID    10
  54. #define CUBESOLID    11
  55. #define BOXSOLID    12
  56. #define TORUSSOLID    13
  57. #define CYLINDERSOLID    14
  58. #define ICOSASOLID    15
  59. #define OCTASOLID    16
  60. #define TETRASOLID    17
  61. #define DODECASOLID    18
  62. #define CONESOLID    19
  63.  
  64. #define PI 3.1415926535897
  65.  
  66. /*    structure for each geometric object    */
  67. typedef struct model {
  68.     GLuint list;    /*  display list to render object   */
  69.     struct model *ptr;    /*  pointer to next object    */
  70.     int numParam;    /*  # of parameters        */
  71.     GLdouble *params;    /*  array with parameters    */
  72. } MODEL, *MODELPTR;
  73.  
  74. /*    array of linked lists--used to keep track of display lists 
  75.  *    for each different type of geometric object.
  76.  */
  77. static MODELPTR lists[25] = {
  78.     NULL, NULL, NULL, NULL, NULL,
  79.     NULL, NULL, NULL, NULL, NULL,
  80.     NULL, NULL, NULL, NULL, NULL,
  81.     NULL, NULL, NULL, NULL, NULL,
  82.     NULL, NULL, NULL, NULL, NULL
  83. };
  84.  
  85. GLuint findList (int index, GLdouble *paramArray, int size);
  86. int compareParams (GLdouble *oneArray, GLdouble *twoArray, int size);
  87. GLuint makeModelPtr (int index, GLdouble *sizeArray, int count);
  88.  
  89. static void drawbox(GLdouble, GLdouble, GLdouble, 
  90.     GLdouble, GLdouble, GLdouble, GLenum);
  91. static void doughnut(GLdouble, GLdouble, GLint, GLint, GLenum);
  92. static void icosahedron(GLdouble *, GLdouble, GLenum);
  93. static void octahedron(GLdouble *, GLdouble, GLenum);
  94. static void tetrahedron(GLdouble *, GLdouble, GLenum);
  95. static void subdivide(int, GLdouble *, GLdouble *, GLdouble *,
  96.     GLdouble *, GLdouble, GLenum, int);
  97. static void drawtriangle(int, int, int,
  98.     GLdouble *, GLdouble, GLenum, int);
  99. static void recorditem(GLdouble *, GLdouble *, GLdouble *,
  100.     GLdouble *, GLdouble, GLenum, int);
  101. static void initdodec(void);
  102. static void dodecahedron(GLdouble *, GLdouble, GLenum);
  103. static void pentagon(int, int, int, int, int, GLenum);
  104.  
  105.  
  106. /*  Render wire frame or solid sphere.  If no display list with
  107.  *  the current model size exists, create a new display list.
  108.  */
  109. void WireSphere (GLdouble radius)
  110. {
  111.     GLUquadricObj *quadObj;
  112.     GLdouble *sizeArray;
  113.     GLuint displayList;
  114.  
  115.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  116.     *sizeArray = radius;
  117.     displayList = findList (SPHEREWIRE, sizeArray, 1);
  118.  
  119.     if (displayList == 0) {
  120.     glNewList(makeModelPtr (SPHEREWIRE, sizeArray, 1),
  121.         GL_COMPILE_AND_EXECUTE);
  122.         quadObj = gluNewQuadric ();
  123.         gluQuadricDrawStyle (quadObj, GLU_LINE);
  124.         gluSphere (quadObj, radius, 16, 16);
  125.     glEndList();
  126.     }
  127.     else {
  128.     glCallList(displayList);
  129.     free (sizeArray);
  130.     }
  131. }
  132.  
  133. void SolidSphere (GLdouble radius)
  134. {
  135.     GLUquadricObj *quadObj;
  136.     GLdouble *sizeArray;
  137.     GLuint displayList;
  138.  
  139.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  140.     *sizeArray = radius;
  141.     displayList = findList (SPHERESOLID, sizeArray, 1);
  142.  
  143.     if (displayList == 0) {
  144.     glNewList(makeModelPtr (SPHERESOLID, sizeArray, 1),
  145.         GL_COMPILE_AND_EXECUTE);
  146.         quadObj = gluNewQuadric ();
  147.         gluQuadricDrawStyle (quadObj, GLU_FILL);
  148.         gluQuadricNormals (quadObj, GLU_SMOOTH);
  149.         gluQuadricTexture( quadObj, GL_TRUE );
  150.         gluSphere (quadObj, radius, 16, 16);
  151.     glEndList();
  152.     }
  153.     else {
  154.     glCallList(displayList);
  155.     free (sizeArray);
  156.     }
  157. }
  158.  
  159. /*  Render wire frame or solid cube.  If no display list with
  160.  *  the current model size exists, create a new display list.
  161.  */
  162. void WireCube (GLdouble size)
  163. {
  164.     GLdouble *sizeArray;
  165.     GLuint displayList;
  166.  
  167.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  168.     *sizeArray = size;
  169.     displayList = findList (CUBEWIRE, sizeArray, 1);
  170.  
  171.     if (displayList == 0) {
  172.     glNewList(makeModelPtr (CUBEWIRE, sizeArray, 1),
  173.         GL_COMPILE_AND_EXECUTE);
  174.         drawbox(-size/2., size/2., -size/2., size/2., 
  175.         -size/2., size/2., GL_LINE_LOOP);
  176.     glEndList();
  177.     }
  178.     else {
  179.     glCallList(displayList);
  180.     free (sizeArray);
  181.     }
  182. }
  183.  
  184. void SolidCube (GLdouble size)
  185. {
  186.     GLdouble *sizeArray;
  187.     GLuint displayList;
  188.  
  189.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  190.     *sizeArray = size;
  191.     displayList = findList (CUBESOLID, sizeArray, 1);
  192.  
  193.     if (displayList == 0) {
  194.     glNewList(makeModelPtr (CUBESOLID, sizeArray, 1),
  195.         GL_COMPILE_AND_EXECUTE);
  196.         drawbox(-size/2., size/2., -size/2., size/2., 
  197.         -size/2., size/2., GL_QUADS);
  198.     glEndList();
  199.     }
  200.     else {
  201.     glCallList(displayList);
  202.     free (sizeArray);
  203.     }
  204. }
  205.  
  206. /*  Render wire frame or solid cube.  If no display list with
  207.  *  the current model size exists, create a new display list.
  208.  */
  209. void WireBox (GLdouble width, GLdouble height, GLdouble depth)
  210. {
  211.     GLdouble *sizeArray, *tmp;
  212.     GLuint displayList;
  213.  
  214.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 3);
  215.     tmp = sizeArray;
  216.     *tmp++ = width;
  217.     *tmp++ = height;
  218.     *tmp++ = depth;
  219.     displayList = findList (BOXWIRE, sizeArray, 3);
  220.  
  221.     if (displayList == 0) {
  222.     glNewList(makeModelPtr (BOXWIRE, sizeArray, 3),
  223.         GL_COMPILE_AND_EXECUTE);
  224.         drawbox(-width/2., width/2., -height/2., height/2., 
  225.         -depth/2., depth/2., GL_LINE_LOOP);
  226.     glEndList();
  227.     }
  228.     else {
  229.     glCallList(displayList);
  230.     free (sizeArray);
  231.     }
  232. }
  233.  
  234. void SolidBox (GLdouble width, GLdouble height, GLdouble depth)
  235. {
  236.     GLdouble *sizeArray, *tmp;
  237.     GLuint displayList;
  238.  
  239.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 3);
  240.     tmp = sizeArray;
  241.     *tmp++ = width;
  242.     *tmp++ = height;
  243.     *tmp++ = depth;
  244.     displayList = findList (BOXSOLID, sizeArray, 3);
  245.  
  246.     if (displayList == 0) {
  247.     glNewList(makeModelPtr (BOXSOLID, sizeArray, 3),
  248.         GL_COMPILE_AND_EXECUTE);
  249.         drawbox(-width/2., width/2., -height/2., height/2., 
  250.         -depth/2., depth/2., GL_QUADS);
  251.     glEndList();
  252.     }
  253.     else {
  254.     glCallList(displayList);
  255.     free (sizeArray);
  256.     }
  257. }
  258.  
  259. /*  Render wire frame or solid tori.  If no display list with
  260.  *  the current model size exists, create a new display list.
  261.  */
  262. void WireTorus (GLdouble innerRadius, GLdouble outerRadius)
  263. {
  264.     GLdouble *sizeArray, *tmp;
  265.     GLuint displayList;
  266.  
  267.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  268.     tmp = sizeArray;
  269.     *tmp++ = innerRadius;
  270.     *tmp++ = outerRadius;
  271.     displayList = findList (TORUSWIRE, sizeArray, 2);
  272.  
  273.     if (displayList == 0) {
  274.     glNewList(makeModelPtr (TORUSWIRE, sizeArray, 2),
  275.         GL_COMPILE_AND_EXECUTE);
  276.         doughnut(innerRadius, outerRadius, 5, 10, GL_LINE_LOOP);
  277.     glEndList();
  278.     }
  279.     else {
  280.     glCallList(displayList);
  281.     free (sizeArray);
  282.     }
  283. }
  284.  
  285. void SolidTorus (GLdouble innerRadius, GLdouble outerRadius)
  286. {
  287.     GLdouble *sizeArray, *tmp;
  288.     GLuint displayList;
  289.  
  290.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  291.     tmp = sizeArray;
  292.     *tmp++ = innerRadius;
  293.     *tmp++ = outerRadius;
  294.     displayList = findList (TORUSSOLID, sizeArray, 2);
  295.  
  296.     if (displayList == 0) {
  297.     glNewList(makeModelPtr (TORUSSOLID, sizeArray, 2),
  298.         GL_COMPILE_AND_EXECUTE);
  299.         doughnut(innerRadius, outerRadius, 8, 15, GL_QUADS);
  300.     glEndList();
  301.     }
  302.     else {
  303.     glCallList(displayList);
  304.     free (sizeArray);
  305.     }
  306. }
  307.  
  308. /*  Render wire frame or solid cylinders.  If no display list with
  309.  *  the current model size exists, create a new display list.
  310.  */
  311. void WireCylinder (GLdouble radius, GLdouble height)
  312. {
  313.     GLUquadricObj *quadObj;
  314.     GLdouble *sizeArray, *tmp;
  315.     GLuint displayList;
  316.  
  317.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  318.     tmp = sizeArray;
  319.     *tmp++ = radius;
  320.     *tmp++ = height;
  321.     displayList = findList (CYLINDERWIRE, sizeArray, 2);
  322.  
  323.     if (displayList == 0) {
  324.     glNewList(makeModelPtr (CYLINDERWIRE, sizeArray, 2),
  325.         GL_COMPILE_AND_EXECUTE);
  326.         glPushMatrix ();
  327.         glRotatef (90.0, 1.0, 0.0, 0.0);
  328.         glTranslatef (0.0, 0.0, -height/2);
  329.         quadObj = gluNewQuadric ();
  330.         gluQuadricDrawStyle (quadObj, GLU_LINE);
  331.         gluCylinder (quadObj, radius, radius, height, 12, 2);
  332.         glPopMatrix ();
  333.     glEndList();
  334.     }
  335.     else {
  336.     glCallList(displayList);
  337.     free (sizeArray);
  338.     }
  339. }
  340.  
  341. void SolidCylinder (GLdouble radius, GLdouble height)
  342. {
  343.     GLUquadricObj *quadObj;
  344.     GLdouble *sizeArray, *tmp;
  345.     GLuint displayList;
  346.  
  347.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  348.     tmp = sizeArray;
  349.     *tmp++ = radius;
  350.     *tmp++ = height;
  351.     displayList = findList (CYLINDERSOLID, sizeArray, 2);
  352.  
  353.     if (displayList == 0) {
  354.     glNewList(makeModelPtr (CYLINDERSOLID, sizeArray, 2),
  355.         GL_COMPILE_AND_EXECUTE);
  356.         glPushMatrix ();
  357.         glRotatef (90.0, 1.0, 0.0, 0.0);
  358.         glTranslatef (0.0, 0.0, -height/2);
  359.         quadObj = gluNewQuadric ();
  360.         gluQuadricDrawStyle (quadObj, GLU_FILL);
  361.         gluQuadricNormals (quadObj, GLU_SMOOTH);
  362.         gluQuadricTexture( quadObj, GL_TRUE );
  363.         gluCylinder (quadObj, radius, radius, height, 12, 2);
  364.         glPopMatrix ();
  365.     glEndList();
  366.     }
  367.     else {
  368.     glCallList(displayList);
  369.     free (sizeArray);
  370.     }
  371. }
  372.  
  373. /*  Render wire frame or solid icosahedra.  If no display list with
  374.  *  the current model size exists, create a new display list.
  375.  */
  376. void WireIcosahedron (GLdouble radius)
  377. {
  378.     GLdouble *sizeArray;
  379.     GLuint displayList;
  380.     GLdouble center[3] = {0.0, 0.0, 0.0};
  381.  
  382.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  383.     *sizeArray = radius;
  384.     displayList = findList (ICOSAWIRE, sizeArray, 1);
  385.  
  386.     if (displayList == 0) {
  387.     glNewList(makeModelPtr (ICOSAWIRE, sizeArray, 1),
  388.         GL_COMPILE_AND_EXECUTE);
  389.         icosahedron (center, radius, GL_LINE_LOOP);
  390.     glEndList();
  391.     }
  392.     else {
  393.     glCallList(displayList);
  394.     free (sizeArray);
  395.     }
  396. }
  397.  
  398. void SolidIcosahedron (GLdouble radius)
  399. {
  400.     GLdouble *sizeArray;
  401.     GLuint displayList;
  402.     GLdouble center[3] = {0.0, 0.0, 0.0};
  403.  
  404.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  405.     *sizeArray = radius;
  406.     displayList = findList (ICOSASOLID, sizeArray, 1);
  407.  
  408.     if (displayList == 0) {
  409.     glNewList(makeModelPtr (ICOSASOLID, sizeArray, 1),
  410.         GL_COMPILE_AND_EXECUTE);
  411.         icosahedron (center, radius, GL_TRIANGLES);
  412.     glEndList();
  413.     }
  414.     else {
  415.     glCallList(displayList);
  416.     free (sizeArray);
  417.     }
  418. }
  419.  
  420. /*  Render wire frame or solid octahedra.  If no display list with
  421.  *  the current model size exists, create a new display list.
  422.  */
  423. void WireOctahedron (GLdouble radius)
  424. {
  425.     GLdouble *sizeArray;
  426.     GLuint displayList;
  427.     GLdouble center[3] = {0.0, 0.0, 0.0};
  428.  
  429.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  430.     *sizeArray = radius;
  431.     displayList = findList (OCTAWIRE, sizeArray, 1);
  432.  
  433.     if (displayList == 0) {
  434.     glNewList(makeModelPtr (OCTAWIRE, sizeArray, 1),
  435.         GL_COMPILE_AND_EXECUTE);
  436.         octahedron (center, radius, GL_LINE_LOOP);
  437.     glEndList();
  438.     }
  439.     else {
  440.     glCallList(displayList);
  441.     free (sizeArray);
  442.     }
  443. }
  444.  
  445. void SolidOctahedron (GLdouble radius)
  446. {
  447.     GLdouble *sizeArray;
  448.     GLuint displayList;
  449.     GLdouble center[3] = {0.0, 0.0, 0.0};
  450.  
  451.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  452.     *sizeArray = radius;
  453.     displayList = findList (OCTASOLID, sizeArray, 1);
  454.  
  455.     if (displayList == 0) {
  456.     glNewList(makeModelPtr (OCTASOLID, sizeArray, 1),
  457.         GL_COMPILE_AND_EXECUTE);
  458.         octahedron (center, radius, GL_TRIANGLES);
  459.     glEndList();
  460.     }
  461.     else {
  462.     glCallList(displayList);
  463.     free (sizeArray);
  464.     }
  465. }
  466.  
  467. /*  Render wire frame or solid tetrahedra.  If no display list with
  468.  *  the current model size exists, create a new display list.
  469.  */
  470. void WireTetrahedron (GLdouble radius)
  471. {
  472.     GLdouble *sizeArray;
  473.     GLuint displayList;
  474.     GLdouble center[3] = {0.0, 0.0, 0.0};
  475.  
  476.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  477.     *sizeArray = radius;
  478.     displayList = findList (TETRAWIRE, sizeArray, 1);
  479.  
  480.     if (displayList == 0) {
  481.     glNewList(makeModelPtr (TETRAWIRE, sizeArray, 1),
  482.         GL_COMPILE_AND_EXECUTE);
  483.         tetrahedron (center, radius, GL_LINE_LOOP);
  484.     glEndList();
  485.     }
  486.     else {
  487.     glCallList(displayList);
  488.     free (sizeArray);
  489.     }
  490. }
  491.  
  492. void SolidTetrahedron (GLdouble radius)
  493. {
  494.     GLdouble *sizeArray;
  495.     GLuint displayList;
  496.     GLdouble center[3] = {0.0, 0.0, 0.0};
  497.  
  498.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  499.     *sizeArray = radius;
  500.     displayList = findList (TETRASOLID, sizeArray, 1);
  501.  
  502.     if (displayList == 0) {
  503.     glNewList(makeModelPtr (TETRASOLID, sizeArray, 1),
  504.         GL_COMPILE_AND_EXECUTE);
  505.         tetrahedron (center, radius, GL_TRIANGLES);
  506.     glEndList();
  507.     }
  508.     else {
  509.     glCallList(displayList);
  510.     free (sizeArray);
  511.     }
  512. }
  513.  
  514. /*  Render wire frame or solid dodecahedra.  If no display list with
  515.  *  the current model size exists, create a new display list.
  516.  */
  517. void WireDodecahedron (GLdouble radius)
  518. {
  519.     GLdouble *sizeArray;
  520.     GLuint displayList;
  521.     GLdouble center[3] = {0.0, 0.0, 0.0};
  522.  
  523.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  524.     *sizeArray = radius;
  525.     displayList = findList (DODECAWIRE, sizeArray, 1);
  526.  
  527.     if (displayList == 0) {
  528.     glNewList(makeModelPtr (DODECAWIRE, sizeArray, 1),
  529.         GL_COMPILE_AND_EXECUTE);
  530.         dodecahedron (center, radius/1.73, GL_LINE_LOOP);
  531.     glEndList();
  532.     }
  533.     else {
  534.     glCallList(displayList);
  535.     free (sizeArray);
  536.     }
  537. }
  538.  
  539. void SolidDodecahedron (GLdouble radius)
  540. {
  541.     GLdouble *sizeArray;
  542.     GLuint displayList;
  543.     GLdouble center[3] = {0.0, 0.0, 0.0};
  544.  
  545.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  546.     *sizeArray = radius;
  547.     displayList = findList (DODECASOLID, sizeArray, 1);
  548.  
  549.     if (displayList == 0) {
  550.     glNewList(makeModelPtr (DODECASOLID, sizeArray, 1),
  551.         GL_COMPILE_AND_EXECUTE);
  552.         dodecahedron (center, radius/1.73, GL_TRIANGLE_FAN);
  553.     glEndList();
  554.     }
  555.     else {
  556.     glCallList(displayList);
  557.     free (sizeArray);
  558.     }
  559. }
  560.  
  561. /*  Render wire frame or solid cones.  If no display list with
  562.  *  the current model size exists, create a new display list.
  563.  */
  564. void WireCone (GLdouble base, GLdouble height)
  565. {
  566.     GLUquadricObj *quadObj;
  567.     GLdouble *sizeArray, *tmp;
  568.     GLuint displayList;
  569.  
  570.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  571.     tmp = sizeArray;
  572.     *tmp++ = base;
  573.     *tmp++ = height;
  574.     displayList = findList (CONEWIRE, sizeArray, 2);
  575.  
  576.     if (displayList == 0) {
  577.     glNewList(makeModelPtr (CONEWIRE, sizeArray, 2),
  578.         GL_COMPILE_AND_EXECUTE);
  579.         quadObj = gluNewQuadric ();
  580.         gluQuadricDrawStyle (quadObj, GLU_LINE);
  581.         gluCylinder (quadObj, base, 0.0, height, 15, 10);
  582.     glEndList();
  583.     }
  584.     else {
  585.     glCallList(displayList);
  586.     free (sizeArray);
  587.     }
  588. }
  589.  
  590. void SolidCone (GLdouble base, GLdouble height)
  591. {
  592.     GLUquadricObj *quadObj;
  593.     GLdouble *sizeArray, *tmp;
  594.     GLuint displayList;
  595.  
  596.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  597.     tmp = sizeArray;
  598.     *tmp++ = base;
  599.     *tmp++ = height;
  600.     displayList = findList (CONESOLID, sizeArray, 2);
  601.  
  602.     if (displayList == 0) {
  603.     glNewList(makeModelPtr (CONESOLID, sizeArray, 2),
  604.         GL_COMPILE_AND_EXECUTE);
  605.         quadObj = gluNewQuadric ();
  606.         gluQuadricDrawStyle (quadObj, GLU_FILL);
  607.         gluQuadricNormals (quadObj, GLU_SMOOTH);
  608.         gluQuadricTexture( quadObj, GL_TRUE );
  609.         gluCylinder (quadObj, base, 0.0, height, 15, 10);
  610.     glEndList();
  611.     }
  612.     else {
  613.     glCallList(displayList);
  614.     free (sizeArray);
  615.     }
  616. }
  617.  
  618. /* Routines to build 3 dimensional solids, including:
  619.  *
  620.  * drawbox, doughnut, icosahedron, 
  621.  * octahedron, tetrahedron, dodecahedron.
  622.  */
  623.  
  624. /* drawbox:
  625.  *
  626.  * draws a rectangular box with the given x, y, and z ranges.  
  627.  * The box is axis-aligned.
  628.  */
  629. void drawbox(GLdouble x0, GLdouble x1, GLdouble y0, GLdouble y1,
  630.     GLdouble z0, GLdouble z1, GLenum type)
  631. {
  632.     static GLdouble n[6][3] = {
  633.     {-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0},
  634.     {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0}
  635.     };
  636.     static GLint faces[6][4] = {
  637.     { 0, 1, 2, 3 }, { 3, 2, 6, 7 }, { 7, 6, 5, 4 },
  638.     { 4, 5, 1, 0 }, { 5, 6, 2, 1 }, { 7, 4, 0, 3 }
  639.     };
  640.     GLdouble v[8][3], tmp;
  641.     GLint i;
  642.  
  643.     if (x0 > x1) {
  644.     tmp = x0; x0 = x1; x1 = tmp;
  645.     }
  646.     if (y0 > y1) {
  647.     tmp = y0; y0 = y1; y1 = tmp; 
  648.     }
  649.     if (z0 > z1) {
  650.     tmp = z0; z0 = z1; z1 = tmp; 
  651.     }
  652.     v[0][0] = v[1][0] = v[2][0] = v[3][0] = x0;
  653.     v[4][0] = v[5][0] = v[6][0] = v[7][0] = x1;
  654.     v[0][1] = v[1][1] = v[4][1] = v[5][1] = y0;
  655.     v[2][1] = v[3][1] = v[6][1] = v[7][1] = y1;
  656.     v[0][2] = v[3][2] = v[4][2] = v[7][2] = z0;
  657.     v[1][2] = v[2][2] = v[5][2] = v[6][2] = z1;
  658.  
  659.     for (i = 0; i < 6; i++) {
  660.     glBegin(type);
  661.     glNormal3dv(&n[i][0]);
  662.     glVertex3dv(&v[faces[i][0]][0]);
  663.     glNormal3dv(&n[i][0]);
  664.     glVertex3dv(&v[faces[i][1]][0]);
  665.     glNormal3dv(&n[i][0]);
  666.     glVertex3dv(&v[faces[i][2]][0]);
  667.     glNormal3dv(&n[i][0]);
  668.     glVertex3dv(&v[faces[i][3]][0]);
  669.     glEnd();
  670.     }
  671. }
  672.  
  673. /* doughnut:
  674.  *
  675.  * draws a doughnut, centered at (0, 0, 0) whose axis is aligned with
  676.  * the z-axis.  The doughnut's major radius is R, and minor radius is r.
  677.  */
  678.  
  679. void doughnut(GLdouble r, GLdouble R, GLint nsides, GLint rings, GLenum type)
  680. {
  681.     int    i, j;
  682.     GLdouble    theta, phi, theta1, phi1;
  683.     GLdouble    p0[03], p1[3], p2[3], p3[3];
  684.     GLdouble    n0[3], n1[3], n2[3], n3[3];
  685.  
  686.     for (i = 0; i < rings; i++) {
  687.     theta = (GLdouble)i*2.0*PI/rings;
  688.     theta1 = (GLdouble)(i+1)*2.0*PI/rings;
  689.     for (j = 0; j < nsides; j++) {
  690.         phi = (GLdouble)j*2.0*PI/nsides;
  691.         phi1 = (GLdouble)(j+1)*2.0*PI/nsides;
  692.  
  693.         p0[0] = cos(theta)*(R + r*cos(phi));
  694.         p0[1] = -sin(theta)*(R + r*cos(phi));
  695.         p0[2] = r*sin(phi);
  696.  
  697.         p1[0] = cos(theta1)*(R + r*cos(phi));
  698.         p1[1] = -sin(theta1)*(R + r*cos(phi));
  699.         p1[2] = r*sin(phi);
  700.  
  701.         p2[0] = cos(theta1)*(R + r*cos(phi1));
  702.         p2[1] = -sin(theta1)*(R + r*cos(phi1));
  703.         p2[2] = r*sin(phi1);
  704.  
  705.         p3[0] = cos(theta)*(R + r*cos(phi1));
  706.         p3[1] = -sin(theta)*(R + r*cos(phi1));
  707.         p3[2] = r*sin(phi1);
  708.  
  709.         n0[0] = cos(theta)*(cos(phi));
  710.         n0[1] = -sin(theta)*(cos(phi));
  711.         n0[2] = sin(phi);
  712.  
  713.         n1[0] = cos(theta1)*(cos(phi));
  714.         n1[1] = -sin(theta1)*(cos(phi));
  715.         n1[2] = sin(phi);
  716.  
  717.         n2[0] = cos(theta1)*(cos(phi1));
  718.         n2[1] = -sin(theta1)*(cos(phi1));
  719.         n2[2] = sin(phi1);
  720.  
  721.         n3[0] = cos(theta)*(cos(phi1));
  722.         n3[1] = -sin(theta)*(cos(phi1));
  723.         n3[2] = sin(phi1);
  724.  
  725.         m_xformpt(p0, p0, n0, n0);
  726.         m_xformpt(p1, p1, n1, n1);
  727.         m_xformpt(p2, p2, n2, n2);
  728.         m_xformpt(p3, p3, n3, n3);
  729.  
  730.         glBegin(type);
  731.         glNormal3dv(n3);
  732.         glVertex3dv(p3);
  733.         glNormal3dv(n2);
  734.         glVertex3dv(p2);
  735.         glNormal3dv(n1);
  736.         glVertex3dv(p1);
  737.         glNormal3dv(n0);
  738.         glVertex3dv(p0);
  739.         glEnd();
  740.     }
  741.     }
  742. }
  743.  
  744. /* octahedron data: The octahedron produced is centered 
  745.  * at the origin and has radius 1.0 
  746.  */
  747. static GLdouble odata[6][3] = {
  748.   {1.0, 0.0, 0.0},
  749.   {-1.0, 0.0, 0.0},
  750.   {0.0, 1.0, 0.0},
  751.   {0.0, -1.0, 0.0},
  752.   {0.0, 0.0, 1.0},
  753.   {0.0, 0.0, -1.0}
  754. };
  755.  
  756. static int ondex[8][3] = {
  757.     {0, 4, 2}, {1, 2, 4}, {0, 3, 4}, {1, 4, 3},
  758.     {0, 2, 5}, {1, 5, 2}, {0, 5, 3}, {1, 3, 5}
  759. };
  760.  
  761. /* tetrahedron data: */
  762.  
  763. #define T    1.73205080756887729
  764.  
  765. static GLdouble tdata[4][3] = {
  766.     {T, T, T}, {T, -T, -T}, {-T, T, -T}, {-T, -T, T}
  767. };
  768.  
  769. static int tndex[4][3] = {
  770.     {0, 1, 3}, {2, 1, 0}, {3, 2, 0}, {1, 2, 3}
  771. };
  772.  
  773. /* icosahedron data: These numbers are rigged to 
  774.  * make an icosahedron of radius 1.0 
  775.  */
  776.  
  777. #define X .525731112119133606
  778. #define Z .850650808352039932
  779.  
  780. static GLdouble idata[12][3] = {
  781.   {-X, 0, Z},
  782.   {X, 0, Z},
  783.   {-X, 0, -Z},
  784.   {X, 0, -Z},
  785.   {0, Z, X},
  786.   {0, Z, -X},
  787.   {0, -Z, X},
  788.   {0, -Z, -X},
  789.   {Z, X, 0},
  790.   {-Z, X, 0},
  791.   {Z, -X, 0},
  792.   {-Z, -X, 0}
  793. };
  794.  
  795. static int index[20][3] = {
  796.     {0, 4, 1},    {0, 9, 4},
  797.     {9, 5, 4},    {4, 5, 8},
  798.     {4, 8, 1},    {8, 10, 1},
  799.     {8, 3, 10},    {5, 3, 8},
  800.     {5, 2, 3},    {2, 7, 3},
  801.     {7, 10, 3},    {7, 6, 10},
  802.     {7, 11, 6},    {11, 0, 6},
  803.     {0, 1, 6},    {6, 1, 10},
  804.     {9, 0, 11},    {9, 11, 2},
  805.     {9, 2, 5},    {7, 2, 11},
  806. };
  807.  
  808. /* icosahedron:
  809.  *
  810.  * Draws an icosahedron with center at p0 having the
  811.  * given radius.
  812.  */
  813.  
  814. static void icosahedron(GLdouble p0[3], GLdouble radius, GLenum shadeType)
  815. {
  816.     int i;
  817.  
  818.     for (i = 0; i < 20; i++)
  819.     drawtriangle(i, 0, 1, p0, radius, shadeType, 0);
  820. }
  821.  
  822. /* octahedron:
  823.  *
  824.  * Draws an octahedron with center at p0 having the
  825.  * given radius.
  826.  */
  827. static void octahedron(GLdouble p0[3], GLdouble radius, GLenum shadeType)
  828. {
  829.     int i;
  830.  
  831.     for (i = 0; i < 8; i++)
  832.     drawtriangle(i, 1, 1, p0, radius, shadeType, 0);
  833. }
  834.  
  835. /* tetrahedron:
  836.  *
  837.  * Draws an tetrahedron with center at p0 having the
  838.  * given radius.
  839.  */
  840.  
  841. static void tetrahedron(GLdouble p0[3], GLdouble radius, GLenum shadeType)
  842. {
  843.     int i;
  844.  
  845.     for (i = 0; i < 4; i++)
  846.     drawtriangle(i, 2, 1, p0, radius, shadeType, 0);
  847. }
  848.  
  849. static void subdivide(int depth, GLdouble *v0, GLdouble *v1, GLdouble *v2,
  850.     GLdouble p0[3], GLdouble radius, GLenum shadeType, int avnormal)
  851. {
  852.     GLdouble w0[3], w1[3], w2[3];
  853.     GLdouble l;
  854.     int i, j, k, n;
  855.  
  856.     for (i = 0; i < depth; i++)
  857.     for (j = 0; i + j < depth; j++) {
  858.         k = depth - i - j;
  859.         for (n = 0; n < 3; n++) {
  860.         w0[n] = (i*v0[n] + j*v1[n] + k*v2[n])/depth;
  861.         w1[n] = ((i+1)*v0[n] + j*v1[n] + (k-1)*v2[n])/depth;
  862.         w2[n] = (i*v0[n] + (j+1)*v1[n] + (k-1)*v2[n])/depth;
  863.         }
  864.         l = sqrt(w0[0]*w0[0] + w0[1]*w0[1] + w0[2]*w0[2]);
  865.         w0[0] /= l; w0[1] /= l; w0[2] /= l;
  866.         l = sqrt(w1[0]*w1[0] + w1[1]*w1[1] + w1[2]*w1[2]);
  867.         w1[0] /= l; w1[1] /= l; w1[2] /= l;
  868.         l = sqrt(w2[0]*w2[0] + w2[1]*w2[1] + w2[2]*w2[2]);
  869.         w2[0] /= l; w2[1] /= l; w2[2] /= l;
  870.         recorditem(w1, w0, w2, p0, radius, shadeType, avnormal);
  871.     }
  872.     for (i = 0; i < depth-1; i++)
  873.     for (j = 0; i + j < depth-1; j++) {
  874.         k = depth - i - j;
  875.         for (n = 0; n < 3; n++) {
  876.         w0[n] = ((i+1)*v0[n] + (j+1)*v1[n] + (k-2)*v2[n])/depth;
  877.         w1[n] = ((i+1)*v0[n] + j*v1[n] + (k-1)*v2[n])/depth;
  878.         w2[n] = (i*v0[n] + (j+1)*v1[n] + (k-1)*v2[n])/depth;
  879.         }
  880.         l = sqrt(w0[0]*w0[0] + w0[1]*w0[1] + w0[2]*w0[2]);
  881.         w0[0] /= l; w0[1] /= l; w0[2] /= l;
  882.         l = sqrt(w1[0]*w1[0] + w1[1]*w1[1] + w1[2]*w1[2]);
  883.         w1[0] /= l; w1[1] /= l; w1[2] /= l;
  884.         l = sqrt(w2[0]*w2[0] + w2[1]*w2[1] + w2[2]*w2[2]);
  885.         w2[0] /= l; w2[1] /= l; w2[2] /= l;
  886.         recorditem(w0, w1, w2, p0, radius, shadeType, avnormal);
  887.     }
  888. }
  889.  
  890. static void drawtriangle(int i, int geomType, int depth,
  891.     GLdouble p0[3], GLdouble radius, GLenum shadeType, int avnormal)
  892. {
  893.     GLdouble *x0, *x1, *x2;
  894.  
  895.     switch (geomType) {
  896.     case 0:    /* icosahedron */
  897.         x0 = &idata[index[i][0]][0];
  898.         x1 = &idata[index[i][1]][0];
  899.         x2 = &idata[index[i][2]][0];
  900.         break;
  901.     case 1: /* octahedron */
  902.         x0 = &odata[ondex[i][0]][0];
  903.         x1 = &odata[ondex[i][1]][0];
  904.         x2 = &odata[ondex[i][2]][0];
  905.         break;
  906.     case 2: /* tetrahedron */
  907.         x0 = &tdata[tndex[i][0]][0];
  908.         x1 = &tdata[tndex[i][1]][0];
  909.         x2 = &tdata[tndex[i][2]][0];
  910.         break;
  911.     }
  912.     subdivide(depth, x0, x1, x2, p0, radius, shadeType, avnormal);
  913. }
  914.  
  915. static void recorditem(GLdouble *n1, GLdouble *n2, GLdouble *n3,
  916.     GLdouble center[3], GLdouble radius, GLenum shadeType, int avnormal)
  917. {
  918.     GLdouble p1[3], p2[3], p3[3], q0[3], q1[3], n11[3], n22[3], n33[3];
  919.     int    i;
  920.  
  921.     for (i = 0; i < 3; i++) {
  922.     p1[i] = n1[i]*radius + center[i];
  923.     p2[i] = n2[i]*radius + center[i];
  924.     p3[i] = n3[i]*radius + center[i];
  925.     }
  926.     if (avnormal == 0) {
  927.     diff3(p1, p2, q0);
  928.     diff3(p2, p3, q1);
  929.     crossprod(q0, q1, q1);
  930.     normalize(q1);
  931.     m_xformpt(p1, p1, q1, n11);
  932.     m_xformptonly(p2, p2);
  933.     m_xformptonly(p3, p3);
  934.  
  935.     glBegin (shadeType);
  936.     glNormal3dv(n11);
  937.     glVertex3dv(p1);
  938.     glVertex3dv(p2);
  939.     glVertex3dv(p3);
  940.     glEnd();
  941.     return;
  942.     }
  943.     m_xformpt(p1, p1, n1, n11);
  944.     m_xformpt(p2, p2, n2, n22);
  945.     m_xformpt(p3, p3, n3, n33);
  946.  
  947.     glBegin (shadeType);
  948.     glNormal3dv(n11);
  949.     glVertex3dv(p1);
  950.     glNormal3dv(n22);
  951.     glVertex3dv(p2);
  952.     glNormal3dv(n33);
  953.     glVertex3dv(p3);
  954.     glEnd();
  955. }
  956.  
  957. static GLdouble dodec[20][3];
  958.  
  959. static void initdodec()
  960. {
  961.     GLdouble alpha, beta;
  962.  
  963.     alpha = sqrt(2.0/(3.0 + sqrt(5.0)));
  964.     beta = 1.0 + sqrt(6.0/(3.0 + sqrt(5.0)) - 2.0 + 2.0*sqrt(2.0/(3.0 +
  965.                                 sqrt(5.0))));
  966.     dodec[0][0] = -alpha; dodec[0][1] = 0; dodec[0][2] = beta;
  967.     dodec[1][0] = alpha; dodec[1][1] = 0; dodec[1][2] = beta;
  968.     dodec[2][0] = -1; dodec[2][1] = -1; dodec[2][2] = -1;
  969.     dodec[3][0] = -1; dodec[3][1] = -1; dodec[3][2] = 1;
  970.     dodec[4][0] = -1; dodec[4][1] = 1; dodec[4][2] = -1;
  971.     dodec[5][0] = -1; dodec[5][1] = 1; dodec[5][2] = 1;
  972.     dodec[6][0] = 1; dodec[6][1] = -1; dodec[6][2] = -1;
  973.     dodec[7][0] = 1; dodec[7][1] = -1; dodec[7][2] = 1;
  974.     dodec[8][0] = 1; dodec[8][1] = 1; dodec[8][2] = -1;
  975.     dodec[9][0] = 1; dodec[9][1] = 1; dodec[9][2] = 1;
  976.     dodec[10][0] = beta; dodec[10][1] = alpha; dodec[10][2] = 0;
  977.     dodec[11][0] = beta; dodec[11][1] = -alpha; dodec[11][2] = 0;
  978.     dodec[12][0] = -beta; dodec[12][1] = alpha; dodec[12][2] = 0;
  979.     dodec[13][0] = -beta; dodec[13][1] = -alpha; dodec[13][2] = 0;
  980.     dodec[14][0] = -alpha; dodec[14][1] = 0; dodec[14][2] = -beta;
  981.     dodec[15][0] = alpha; dodec[15][1] = 0; dodec[15][2] = -beta;
  982.     dodec[16][0] = 0; dodec[16][1] = beta; dodec[16][2] = alpha;
  983.     dodec[17][0] = 0; dodec[17][1] = beta; dodec[17][2] = -alpha;
  984.     dodec[18][0] = 0; dodec[18][1] = -beta; dodec[18][2] = alpha;
  985.     dodec[19][0] = 0; dodec[19][1] = -beta; dodec[19][2] = -alpha;
  986. }
  987.  
  988. /* dodecahedron:
  989.  *
  990.  * Draws an dodecahedron with center at 0.0. The radius
  991.  * is sqrt(3).
  992.  */
  993. static void dodecahedron(GLdouble center[3], GLdouble sc, GLenum type)
  994. {
  995.     static int inited = 0;
  996.  
  997.     if ( inited == 0) {
  998.     inited = 1;
  999.     initdodec();
  1000.     }
  1001.     m_pushmatrix();
  1002.     m_translate(center[0], center[1], center[2]);
  1003.     m_scale(sc, sc, sc);
  1004.     pentagon(0, 1, 9, 16, 5, type);
  1005.     pentagon(1, 0, 3, 18, 7, type);
  1006.     pentagon(1, 7, 11, 10, 9, type);
  1007.     pentagon(11, 7, 18, 19, 6, type);
  1008.     pentagon(8, 17, 16, 9, 10, type);
  1009.     pentagon(2, 14, 15, 6, 19, type);
  1010.     pentagon(2, 13, 12, 4, 14, type);
  1011.     pentagon(2, 19, 18, 3, 13, type);
  1012.     pentagon(3, 0, 5, 12, 13, type);
  1013.     pentagon(6, 15, 8, 10, 11, type);
  1014.     pentagon(4, 17, 8, 15, 14, type);
  1015.     pentagon(4, 12, 5, 16, 17, type);
  1016.     m_popmatrix();
  1017. }
  1018.  
  1019. static void pentagon(int a, int b, int c, int d, int e, GLenum shadeType)
  1020. {
  1021.     GLdouble n0[3], d1[3], d2[3], d3[3], d4[3], d5[3], nout[3];
  1022.  
  1023.     diff3(&dodec[a][0], &dodec[b][0], d1);
  1024.     diff3(&dodec[b][0], &dodec[c][0], d2);
  1025.     crossprod(d1, d2, n0);
  1026.     normalize(n0);
  1027.     m_xformpt(&dodec[a][0], d1, n0, nout);
  1028.     m_xformptonly(&dodec[b][0], d2);
  1029.     m_xformptonly(&dodec[c][0], d3);
  1030.     m_xformptonly(&dodec[d][0], d4);
  1031.     m_xformptonly(&dodec[e][0], d5);
  1032.  
  1033.     glBegin (shadeType);
  1034.     glNormal3dv(nout);
  1035.     glVertex3dv(d1);
  1036.     glVertex3dv(d2);
  1037.     glVertex3dv(d3);
  1038.     glVertex3dv(d4);
  1039.     glVertex3dv(d5);
  1040.     glEnd();
  1041. }
  1042.  
  1043. /*    linked lists--display lists for each different 
  1044.  *    type of geometric objects.  The linked list is 
  1045.  *    searched, until an object of the requested
  1046.  *    size is found.  If no geometric object of that size
  1047.  *    has been previously made, a new one is created.
  1048.  */
  1049. GLuint findList (int index, GLdouble *paramArray, int size) 
  1050. {
  1051.     MODELPTR endList;
  1052.     int found = 0;
  1053.     
  1054.     endList = lists[index];
  1055.     while (endList != NULL) {
  1056.     if (compareParams (endList->params, paramArray, size))
  1057.         return (endList->list);
  1058.     endList = endList->ptr;
  1059.     }
  1060. /*  if not found, return 0 and calling routine should
  1061.  *  make a new list    
  1062.  */
  1063.     return (0);
  1064. }
  1065.  
  1066. int compareParams (GLdouble *oneArray, GLdouble *twoArray, int size) 
  1067. {
  1068.     int i;
  1069.     int matches = 1;
  1070.  
  1071.     for (i = 0; (i < size) && matches; i++) {
  1072.     if (*oneArray++ != *twoArray++)
  1073.         matches = 0;
  1074.     }
  1075.     return (matches);
  1076. }
  1077.  
  1078. GLuint makeModelPtr (int index, GLdouble *sizeArray, int count)
  1079. {
  1080.     MODELPTR newModel;
  1081.  
  1082.     newModel = (MODELPTR) malloc (sizeof (MODEL));
  1083.     newModel->list = glGenLists (1);
  1084.     newModel->numParam = count;
  1085.     newModel->params = sizeArray;
  1086.     newModel->ptr = lists[index];
  1087.     lists[index] = newModel;
  1088.  
  1089.     return (newModel->list);
  1090. }
  1091.